// 类型检查机制
// TypeScript 编译器在做类型检查时，所秉承的一些原则，以及表现出的一些行为。
//作用： 辅助开发，提升开发效率

// 1,类型推断
// 2,类型兼容性
// 3,类型保护


// 1,类型推断
let a = 1
let b = [1, null]

let c = (x = 1) => x + 1

// window.onkeydown = (event) => {
//   // console.log(event)
// }

// 类型断言
interface Foo {
  bar: number
}
// let foo = {} as Foo
// foo.bar = 1
let foo: Foo = {
  bar: 1
}

// 2,类型兼容性
// 当一个类型Y可以被赋值给另一个类型X时，我们就可以说类型X兼容Y
// X兼容Y: X(目标类型)=Y(源类型)
let s: string = 'a'
// s = null

//接口兼容性
interface X1 {
  a: any;
  b: any;
}

interface Y {
  a: any;
  b: any;
  c: any;
}
let x1: X1 = { a: 1, b: 2 }
let y1: Y = { a: 1, b: 2, c: 3 }
x1 = y1
// y1 = x1  // y1不兼容x1

// 函数的兼容性
type Handler = (a: number, b: number) => void
function hof(handler: Handler) {
  return handler
}
//1)参数个数
let handler1 = (a: number) => { }
hof(handler1)
let handler2 = (a: number, b: number, c: number) => { }
// hof(handler2)

//可选参数和剩余参数
let a1 = (p1: number, p2: number) => { }
let b1 = (p1?: number, p2?: number) => { }
let c1 = (...args: number[]) => { }

// a1 = b1
// a1 = c1
// b1 = c1
// b1 = a1
// c1 = a1
// c1 = b1

//2）参数类型
let handler3 = (a: string) => { }
// hof(handler3)

interface Point3D {
  x: number
  y: number
  z: number
}
interface Point2D {
  x: number
  y: number
}
let p3d = (point: Point3D) => { }
let p2d = (point: Point2D) => { }
p3d = p2d
// p2d = p3d

//3) 返回值类型
let f = () => ({ name: 'alice' })
let g = () => ({ name: 'alice', location: 'beijing' })
f = g
// g = f

// function overload(a: number, b: number): number;
//枚举类型兼容性
enum fruit { apple, banana }
enum color { red, yellow }
let fruit1: fruit.apple = 3
// let color1 = color.red = fruit1.apple

// 类的兼容性
class A11 {
  constructor(p: number, q: number) { }
  id: number = 1
  private name: string = ''
}
class B11 {
  static s = 1
  constructor(p: number) { }
  id: number = 2
  private name: string = ''
}

let aa = new A11(1, 2)
let bb = new B11(1)

// aa = bb
// bb=aa

class C11 extends A11 { }
let cc = new C11(1, 2)
aa = cc
cc = aa

// 泛型的兼容性
interface Empty<T> {
  value: T
}
let obj1: Empty<number>
let obj2: Empty<string>

// obj1 = obj2

// 结构之间兼容： 成员少的兼容成员多的
// 函数之间兼容： 参数多的兼容参数少的